/*
 * MyGraph.java
 *
 * Created on June 8, 2007, 9:06 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package org.jerm.Interface.JGraph_Diagrama;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;

import javax.imageio.ImageIO;
import javax.swing.JFileChooser;
import javax.swing.filechooser.FileFilter;

import org.jgraph.JGraph;
import org.jgraph.graph.DefaultPort;
import org.jgraph.graph.GraphLayoutCache;
import org.jgraph.graph.GraphModel;

/**
 * JGraph Levimente Modificado
 * @author Tiago Falcao
 */
public class MyGraph extends JGraph {

        JFileChooser fileChooser;
    
        /**
         * Construct the Graph using the Model as its Data Source
         * @param model Modelo de JGraph
         */
        public MyGraph(GraphModel model) {
                this(model, null);
        }

        /**
         * Construct the Graph using the Model as its Data Source
         * @param model Modelo de JGraph
         * @param cache Cache do JGraph
         */
        public MyGraph(GraphModel model, GraphLayoutCache cache) {
                super(model, cache);
                // Make Ports Visible by Default
                setPortsVisible(true);
                // Use the Grid (but don't make it Visible)
                setGridEnabled(true);
                // Set the Grid Size to 10 Pixel
                setGridSize(6);
                // Set the Tolerance to 2 Pixel
                setTolerance(2);
                // Accept edits if click on background
                setInvokesStopCellEditing(true);
                // Allows control-drag
                setCloneable(true);
                // Jump to default port on connect
                setJumpToDefaultPort(true);
        }

        /**
         * Retorna Todas Arestas em um Object[] que possuem Bloco na Posicao Determinada
         * @param bloco Bloco(Entidade,Relacionamento,Heranca)
         * @param Posicao Posicao do Bloco nas Arestas. (Aresta.ANY,Aresta.SOURCE,Aresta.TARGET)
         * @return Object[] com as Arestas desejadas.
         */
        public Object[] getArestas(Object bloco,int Posicao){
            ArrayList<Aresta> Arestas=new ArrayList<Aresta>();
            Object[] edges=this.getGraphLayoutCache().getCells(false,false,false,true);
            Aresta aresta;
            int i=0;
            while(i<edges.length){
                aresta=(Aresta)edges[i];
                if(((DefaultPort)aresta.getSource()).getUserObject()==bloco && ((Posicao==Aresta.ANY)||(Posicao==Aresta.SOURCE)))
                    Arestas.add(aresta);
                else if(((DefaultPort)aresta.getTarget()).getUserObject()==bloco && ((Posicao==Aresta.ANY)||(Posicao==Aresta.TARGET)))
                    Arestas.add(aresta);
                i++;
            }
            return Arestas.toArray();
        }
        
        /**
         * Retorna Todas Arestas em um Object[] que possuem Bloco na Posicao Determinada
         * @param bloco Bloco(Entidade,Relacionamento,Heranca)
         * @param Posicao Posicao do Bloco nas Arestas. (Aresta.ANY,Aresta.SOURCE,Aresta.TARGET)
         * @return Object[] com as Arestas desejadas.
         */
        public Object[] getAdjacentes(Object bloco,int Posicao){
            ArrayList<Object> Arestas=new ArrayList<Object>();
            Object[] edges=this.getGraphLayoutCache().getCells(false,false,false,true);
            Aresta aresta;
            int i=0;
            while(i<edges.length){
                aresta=(Aresta)edges[i];
                if(((DefaultPort)aresta.getSource()).getUserObject()==bloco && ((Posicao==Aresta.ANY)||(Posicao==Aresta.SOURCE)))
                    Arestas.add(((DefaultPort)aresta.getTarget()).getUserObject());
                else if(((DefaultPort)aresta.getTarget()).getUserObject()==bloco && ((Posicao==Aresta.ANY)||(Posicao==Aresta.TARGET)))
                    Arestas.add(((DefaultPort)aresta.getSource()).getUserObject());
                i++;
            }
            return Arestas.toArray();
        }
        
        public Object[] getCells(Class<?> classe,int nArestas,int Posicao){
            ArrayList<Object> Vertices=new ArrayList<Object>();
            Object[] vertices=this.getGraphLayoutCache().getCells(false,true,false,false);
            Object[] edges=this.getGraphLayoutCache().getCells(false,false,false,true);
            Aresta aresta;
            int i=0;
            int j;
            int c;
            while(i<vertices.length){
                j=0;
                c=0;
                if(vertices[i].getClass()==classe){
                    while(j<edges.length){
                        aresta=(Aresta)edges[j];
                        if(((DefaultPort)aresta.getSource()).getUserObject()==vertices[i] && ((Posicao==Aresta.ANY)||(Posicao==Aresta.SOURCE)))
                            c++;
                        else if(((DefaultPort)aresta.getTarget()).getUserObject()==vertices[i] && ((Posicao==Aresta.ANY)||(Posicao==Aresta.TARGET)))
                            c++;
                        j++;
                    }
                    if(c==nArestas)
                        Vertices.add(vertices[i]);
                }
                i++;
            }
            return Vertices.toArray();
        }
        
        
        
            /**
     * Conta Quantas Arestas Existem ligando source ao target(ou do target ao source)
     * @param source_port DefaultPort de Inicio da Linha
     * @param target_port DefaultPort de Target da Linha
     * @return int Quantidade de Arestas
     */
    public int countAresta(DefaultPort source_port,DefaultPort target_port){
        Object[] edges=this.getGraphLayoutCache().getCells(false,false,false,true);
        Aresta aresta;
        int i=0;
        int j=0;
        while(i<edges.length){
            aresta=(Aresta)edges[i];
            if((aresta.getSource()==source_port && aresta.getTarget()==target_port)
                ||(aresta.getSource()==target_port && aresta.getTarget()==source_port))
                j++;
            i++;
        }
        return j;
    }
    
    /**
     * Se ja existe uma Aresta ligando source ao target(ou do target ao source)
     * @param source_port DefaultPort de Inicio da Linha
     * @param target_port DefaultPort de Target da Linha
     * @return boolean True se ja existir
     */
    public boolean hasAresta(DefaultPort source_port,DefaultPort target_port){
        if(countAresta(source_port,target_port)==0)
            return false;
        return true;
    }
    
    /**
     * Se uma porta(herdante_port) ja esta herdando de alguem
     * @param herdado_port DefaultPort Porta
     * @return boolean True se ja existir
     */
    public boolean hasFilhoHeranca(DefaultPort herdante_port){
        Object[] edges=this.getGraphLayoutCache().getCells(false,false,false,true);
        Aresta aresta;
        int i=0;
        while(i<edges.length){
            aresta=(Aresta)edges[i];
            if(aresta.getTarget()==herdante_port && ((DefaultPort)aresta.getSource()).getUserObject().getClass()==Heranca.class)
                return true;
            i++;
        }
        return false;
    }
    
    /**
     * Se uma porta(heranca) de uma Heranca ja tem o pai definido
     * @param heranca_port DefaultPort de uma Heranca
     * @return boolean True se ja existir
     */
    public boolean hasPaiHeranca(DefaultPort heranca_port){
        Object[] edges=this.getGraphLayoutCache().getCells(false,false,false,true);
        Aresta aresta;
        int i=0;
        while(i<edges.length){
            aresta=(Aresta)edges[i];
            if(aresta.getTarget()==heranca_port)
                return true;
            i++;
        }
        return false;
    }
    
    /**
     * Se um Bloco herda de alguem
     * @param Object Bloco
     * @return boolean True se herdar de alguem
     */
    public boolean isFilhoHeranca(Object Bloco){
        Object[] edges=this.getGraphLayoutCache().getCells(false,false,false,true);
        Aresta aresta;
        int i=0;
        while(i<edges.length){
            aresta=(Aresta)edges[i];
            if(((DefaultPort)aresta.getTarget()).getUserObject()==Bloco && ((DefaultPort)aresta.getSource()).getUserObject().getClass()==Heranca.class)
                return true;
            i++;
        }
        return false;
    }
    
    /**
     * Se alguem herda dele
     * @param Object Bloco
     * @return boolean True se for herdado por alguem
     */
    public boolean isPaiHeranca(Object Bloco){
        Object[] edges=this.getGraphLayoutCache().getCells(false,false,false,true);
        Aresta aresta;
        int i=0;
        while(i<edges.length){
            aresta=(Aresta)edges[i];
            if(((DefaultPort)aresta.getSource()).getUserObject()==Bloco && ((DefaultPort)aresta.getTarget()).getUserObject().getClass()==Heranca.class)
                return true;
            i++;
        }
        return false;
    }

    
    
    public void exportImage(){
		int returnValue = JFileChooser.CANCEL_OPTION;
		initFileChooser();
		returnValue = fileChooser.showSaveDialog(this);
		if (returnValue == JFileChooser.APPROVE_OPTION) {
                    int inset=1;
            try {
                OutputStream out = new FileOutputStream(fileChooser.getSelectedFile());
                Color bg = null; // Use this to make the background transparent
                bg = this.getBackground(); // Use this to use the graph background color
                BufferedImage img = this.getImage(bg, inset);
                ImageIO.write(img, "png", out);
                out.flush();
                out.close();
            } catch (FileNotFoundException ex) {
                new Error("Arquivo não Encontrado");
            } catch (IOException ex) {
                new Error("Error ao gravar Imagem");
            }
		}

    }
    
    
    
    	public void initFileChooser() {
		if (fileChooser == null) {
			fileChooser = new JFileChooser();
			FileFilter fileFilter = new FileFilter() {
				/**
				 * @see javax.swing.filechooser.FileFilter#accept(File)
				 */
				public boolean accept(File f) {
					if (f == null)
						return false;
					if (f.getName() == null)
						return false;
					if (f.getName().endsWith(".png"))
						return true;
					if (f.isDirectory())
						return true;

					return false;
				}

				/**
				 * @see javax.swing.filechooser.FileFilter#getDescription()
				 */
				public String getDescription() {
					return "Imagem PNG";
				}
			};
			fileChooser.setFileFilter(fileFilter);
		}
	}
}
